package com.ydzh.kfqgwvisitor.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.exceptions.ClientException;
import com.baidu.aip.face.AipFace;
import com.baidu.aip.face.FaceVerifyRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ydzh.kfqgwvisitor.base.Result;
import com.ydzh.kfqgwvisitor.common.Constant;
import com.ydzh.kfqgwvisitor.constant.Configure;
import com.ydzh.kfqgwvisitor.constant.VisitorAppointmentURL;
import com.ydzh.kfqgwvisitor.dto.PeerPeopleDTO;
import com.ydzh.kfqgwvisitor.dto.VisitorDTO;
import com.ydzh.kfqgwvisitor.dto.VisitorExcelDTO;
import com.ydzh.kfqgwvisitor.dto.VisitorFaceDTO;
import com.ydzh.kfqgwvisitor.entity.*;
import com.ydzh.kfqgwvisitor.exception.BaseException;
import com.ydzh.kfqgwvisitor.hikdata.hikreq.person.Person;
import com.ydzh.kfqgwvisitor.hikdata.hikreq.records.VisitorRecords;
import com.ydzh.kfqgwvisitor.hikdata.hikreq.visitor.VisitorInfo;
import com.ydzh.kfqgwvisitor.hikdata.hikres.person.PersonData;
import com.ydzh.kfqgwvisitor.hikdata.hikres.person.PersonList;
import com.ydzh.kfqgwvisitor.hikdata.hikres.person.PersonPhotoRes;
import com.ydzh.kfqgwvisitor.hikdata.hikres.records.DesignatedResources;
import com.ydzh.kfqgwvisitor.hikdata.hikres.records.RecordsData;
import com.ydzh.kfqgwvisitor.hikdata.hikres.records.RecordsList;
import com.ydzh.kfqgwvisitor.hikdata.hikres.visitor.VisitorData;
import com.ydzh.kfqgwvisitor.mapper.VisitorMapper;
import com.ydzh.kfqgwvisitor.properties.BaiDuProperties;
import com.ydzh.kfqgwvisitor.properties.Properties;
import com.ydzh.kfqgwvisitor.response.Response;
import com.ydzh.kfqgwvisitor.service.*;
import com.ydzh.kfqgwvisitor.tool.GetCameraPreviewURL;
import com.ydzh.kfqgwvisitor.util.AliSmsUtils;
import com.ydzh.kfqgwvisitor.util.HealthCommissionUtils;
import com.ydzh.kfqgwvisitor.util.IdcardUtil;
import com.ydzh.kfqgwvisitor.util.TimeUtils;
import com.ydzh.kfqgwvisitor.vo.IDCardVo;
import com.ydzh.kfqgwvisitor.vo.PeerPeopleVO;
import org.apache.commons.lang.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 访客信息表  服务实现类
 * </p>
 *
 * @author zcj
 * @since 2021-09-01
 */
@Service
public class VisitorServiceImpl extends ServiceImpl<VisitorMapper, Visitor> implements VisitorService {

    @Autowired
    private VisitorMapper mapper;
    @Autowired
    private BaiDuProperties baiDuProperties;

    @Autowired
    private BeVisitorService beVisitorService;
    @Autowired
    private BeUnitService beUnitService;
    @Autowired
    private BeDepartmentService beDepartmentService;
    @Autowired
    private ShortMessageService shortMessageService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result saveToApply(VisitorDTO visitorDTO) {
        Visitor visitor = BeanUtil.copyProperties(visitorDTO, Visitor.class);
        LocalDateTime now = LocalDateTime.now();
        visitor.setCreateTime(now);
        visitor.setFollowNum(visitorDTO.getPeerPeopleList().size());
        save(visitor);
        List<Visitor> visitorList = new ArrayList<>();
        if (ArrayUtil.isNotEmpty(visitorDTO.getPeerPeopleList())) {
            for (PeerPeopleDTO peerPeopleDTO : visitorDTO.getPeerPeopleList()) {
                Visitor peerVisitor = BeanUtil.copyProperties(peerPeopleDTO, Visitor.class);
                peerVisitor.setLeaderId(visitor.getId());
                peerVisitor.setCreateTime(now);
                visitorList.add(peerVisitor);

            }
            saveBatch(visitorList);
        }

        // 保存到短信数据库
        List<ShortMessage> messageList = new ArrayList<>();
        for (Visitor visitor1 : visitorList) {
            ShortMessage shortMessage = new ShortMessage();
            shortMessage.setVisitorId(visitor1.getId());
            shortMessage.setPhoneNo(visitor1.getPhoneNo());
            shortMessage.setName(visitor1.getVisitorName());
            shortMessage.setMessageType(0);
            shortMessage.setIsRead(0);
            shortMessage.setCreateTime(LocalDateTime.now());
            messageList.add(shortMessage);
        }
        shortMessageService.saveBatch(messageList);

        return Result.buildSuccess();
    }

    @Override
    public Result<com.ydzh.kfqgwvisitor.vo.VisitorVO> visitorInfo(Long visitorId) {
        // 先获得主访客的信息
        Visitor visitor = getById(visitorId);
        com.ydzh.kfqgwvisitor.vo.VisitorVO visitorVO = BeanUtil.copyProperties(visitor, com.ydzh.kfqgwvisitor.vo.VisitorVO.class);
        // 查找随从人员
        List<Visitor> visitorList = query().eq("LEADER_ID", visitorId).list();
        List<PeerPeopleVO> peerPeopleVOList = new ArrayList<>();
        if (ArrayUtil.isNotEmpty(visitorList)) {
            for (Visitor visitor1 : visitorList) {
                PeerPeopleVO peerPeopleVO = BeanUtil.copyProperties(visitor1, PeerPeopleVO.class);
                peerPeopleVOList.add(peerPeopleVO);
            }
            visitorVO.setPeerPeopleList(peerPeopleVOList);
        }
        return Result.buildSuccess(visitorVO);
    }

    @Override
    public Result<IDCardVo> idCardInfo(String img) {
        Properties ioc = baiDuProperties.getIoc();
        IdcardUtil idTest = new IdcardUtil(ioc.getAppId(), ioc.getApiKey(), ioc.getSecretKey());
        HashMap<String, String> options = new HashMap<>(2);
        options.put("detect_direction", "true");
        options.put("detect_risk", "true");
        JSONObject jsonObject = idTest.idcard(img, "front", options);
        if (jsonObject.has("error_msg")) {
            return Result.buildError("身份证解析失败，请重新上传");
        }
        JSONObject words_result = jsonObject.getJSONObject("words_result");
        if (Objects.isNull(words_result)) {
            return Result.buildError("身份证解析失败，请重新上传");
        }
        IDCardVo idCardVo = new IDCardVo();
        idCardVo.setUserName(words_result.getJSONObject("姓名").get("words").toString());
        if (StringUtils.isBlank(idCardVo.getUserName())) {
            return Result.buildError("身份证姓名解析失败，请重新上传");
        }
        String gender = words_result.getJSONObject("性别").get("words").toString();
        if (StringUtils.isBlank(gender)) {
            return Result.buildError("身份证性别解析失败，请重新上传");
        }
        idCardVo.setGender("男".equals(gender) ? 1 : 2);

        idCardVo.setIdCard(words_result.getJSONObject("公民身份号码").get("words").toString());
        if (StringUtils.isBlank(idCardVo.getIdCard())) {
            return Result.buildError("身份证身份证号解析失败，请重新上传");
        }
        return Result.buildSuccess(idCardVo);
    }

    @Override
    public Result faceverify(String img) {
        String[] split = img.split(",");
        Properties idcardName = baiDuProperties.getIdcardName();
        AipFace aipFace = new AipFace(idcardName.getAppId(), idcardName.getApiKey(), idcardName.getSecretKey());
        FaceVerifyRequest faceVerifyRequest = new FaceVerifyRequest(split[1], "BASE64");
        List<FaceVerifyRequest> input = new ArrayList<>();
        input.add(faceVerifyRequest);
        JSONObject faceverify = aipFace.faceverify(input);
        if (faceverify.getInt("error_code") != 0) {
            System.out.println("认证失败");
            return Result.buildError("认证失败，请重新拍照");
        }
        if (faceverify.getJSONObject("result").getBigDecimal("face_liveness").compareTo(new BigDecimal("0.95")) == -1) {
            return Result.buildError("认证失败，请重新拍照");
        }
        return Result.buildSuccess();
    }


    /**
     * 通过QRCode查询访客来访记录v2中的访客id(orderId)
     * <p>
     * 这个用作二维码失效之后重新生成二维码(此功能现在不需要 如果需要还需要海康生成访客动态二维码内容联合查询)
     *
     * @param QRCode
     * @return
     */
    @Override
    public String orderIdByQRCode(String QRCode) {

        GetCameraPreviewURL cameraPreviewURL = new GetCameraPreviewURL(Configure.host, Configure.appKey, Configure.appSecret);

        VisitorRecords visitorRecords = new VisitorRecords();

        visitorRecords.setPageNo(1);

        visitorRecords.setPageSize(999);

        visitorRecords.setQRCode(QRCode);

        //海康查询访客来访记录v2 获取访客id
        String s = cameraPreviewURL.doPost(GetCameraPreviewURL.ARTEMIS_PATH + VisitorAppointmentURL.QUERY_VISITOR_RECORDS, JSON.toJSONString(visitorRecords));

        net.sf.json.JSONObject jsonObjectP = net.sf.json.JSONObject.fromObject(s);

        Map<String, Class> classMap = new HashMap<>();

        //组装海康门禁返回数据
        classMap.put("data", RecordsData.class);

        classMap.put("list", RecordsList.class);

        classMap.put("designatedResources", DesignatedResources.class);

        Result recordsResult = (Result) net.sf.json.JSONObject.toBean(jsonObjectP, Result.class, classMap);

        RecordsData data = (RecordsData) recordsResult.getData();

        List<RecordsList> list = data.getList();

        String orderId = "";

        for (RecordsList rl : list) {
            orderId = rl.getOrderId();
        }

        return orderId;
    }

    /**
     * 通过身份证号查询访客信息
     *
     * @param idCardNo
     * @return
     */
    @Override
    public Visitor getByIdCardNo(String idCardNo) {

        return baseMapper.getByIdCardNo(idCardNo);
    }

    /**
     * 点击链接生成访客二维码
     * 返回二维码创建时间及二维码图片的base64是否全程接种疫苗和健康码颜色
     *
     * @param id
     * @return
     */
    @Override
    public Response getQRCode(Long id) {

        Response response = new Response();

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");

        String qrCode = baseMapper.selectById(id).getQRCode();

        if (StringUtils.isNotBlank(qrCode)) {

            String base64Img = BufferedImageToBase64(qrCodeToBufferImage(qrCode));

            response.setQTime(dateTimeFormatter.format(baseMapper.selectById(id).getCreateTime()));

            response.setBase64(base64Img);

            return response;
        }
        List<String> strings = QRCode(id);

        //领导点击同意之后海康返回QRCode的时间
        for (String qr : strings) {

            LambdaQueryWrapper<Visitor> wrapper = new LambdaQueryWrapper<>();

            wrapper.eq(Visitor::getQRCode, qr);

            Visitor one = getOne(wrapper);

            response.setQTime(dateTimeFormatter.format(one.getCreateTime()));

            String base64Img = BufferedImageToBase64(qrCodeToBufferImage(qrCode));

            response.setBase64(base64Img);

        }

        return response;

    }

    /**
     * 点击链接生成访客卫健委
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    public Response getHealthCode(Long id) {

        Response response = new Response();

        //山东省疫苗接种和核酸检测信息查询服务
        response.setFlag(getVaccination(id));

        //获取健康码颜色
        response.setState(getPassCodeColor(id));

        return response;
    }

    /**
     * 把qrCode转成BufferedImage
     *
     * @param qrCode
     * @return
     */
    private BufferedImage qrCodeToBufferImage(String qrCode) {

        //生成二维码配置
        HashMap<EncodeHintType, Object> hints = new HashMap<>();

        //设置纠错等级
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);

        //编码类型
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

        BitMatrix bitMatrix;

        BufferedImage bufferedImage = null;

        try {

            bitMatrix = new MultiFormatWriter().encode(qrCode, BarcodeFormat.QR_CODE, 300, 300, hints);

            //把矩阵写入图像
            bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);

        } catch (WriterException e) {

            e.printStackTrace();

        }

        return bufferedImage;
    }

    /**
     * BufferedImage 编码转换为 base64
     *
     * @param bufferedImage
     * @return
     */
    private String BufferedImageToBase64(BufferedImage bufferedImage) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
        try {
            ImageIO.write(bufferedImage, "jpg", baos);//写入流中
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] bytes = baos.toByteArray();//转换成字节

        String png_base64 = Base64.getEncoder().encodeToString(bytes).trim();//转换成base64串
        png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
        //return 为jpg格式则写jpg ;png则写png
        return "data:image/jpg;base64," + png_base64;
    }

    /**
     * 获取健康码状态
     *
     * @return
     */
    @Override
    public Integer getPassCode(Long id) {

        String apiKeyHealth = "879756510412931072";

        String appIdHealth = "iao4p1fjbq37misom68w";

        String appSecretHealth = "24f8875c9c7d45419acde17d88bb8b62";

        String urlHealth = "http://59.224.6.2/gateway/api/3/checkVaccineStatusExt";

        cn.hutool.json.JSONObject common = Common(apiKeyHealth, appIdHealth, appSecretHealth, urlHealth, id);

        List<Integer> integers = new ArrayList<>();

        Integer status = (Integer) common.getJSONObject("data").getJSONObject("data").getJSONObject("data").get("status");

        return status;
    }

    /**
     * 山东省疫苗接种和核酸检测信息查询服务
     *
     * @param id
     * @return
     */
    @Override
    public Integer getVaccination(Long id) {

        String apiKeyHealth = "879756809923985408";

        String appIdHealth = "iao4p1fjbq37misom68w";

        String appSecretHealth = "24f8875c9c7d45419acde17d88bb8b62";

        String urlHealth = "http://59.224.6.2/gateway/api/11/getVaccineRecordExt";

        cn.hutool.json.JSONObject common = Common(apiKeyHealth, appIdHealth, appSecretHealth, urlHealth, id);

        Integer flag = (Integer) common.getJSONObject("data").getJSONObject("data").getJSONObject("data").get("flag");

        return flag;
    }

    /**
     * 获取健康码颜色
     *
     * @param id
     * @return
     */
    @Override
    public Integer getPassCodeColor(Long id) {

        String appIdHealth = "iao4p1fjbq37misom68w";

        String appSecretHealth = "24f8875c9c7d45419acde17d88bb8b62";

        String urlHealth = "http://172.20.238.8:4431/passDataExchangeService/dataExchange/getHealthPassByUserInfo";

        cn.hutool.json.JSONObject common1 = Common1(appIdHealth, appSecretHealth, urlHealth, id);

        //是否有健康码：true，有；false，无
        Boolean is = (Boolean) common1.getJSONObject("data").get("isHaveHealthCode");

        if (is) {

            //健康码等级： 0，绿色； 1，黄色； 2，红色；
            Integer state = (Integer) common1.getJSONObject("data").get("state");

            return state;
        }
        //如果集合为空则代表此人没有健康码
        return null;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result upload(MultipartFile multipartFile) {
        ImportParams params = new ImportParams();
        // 头部有两行
        params.setHeadRows(2);
        // params.setTitleRows(0);
        List<VisitorExcelDTO> result = null;
        try {
            result = ExcelImportUtil.importExcel(multipartFile.getInputStream(),
                    VisitorExcelDTO.class, params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 先查询单位的ID(查一次即可)
        BeUnit unit = beUnitService.query().eq("BEUNIT_NAME", result.get(0).getUnit()).one();
        if (Objects.isNull(unit)) {
            return Result.buildError("部门不存在,excel部门获得为" + result.get(0).getUnit());
        }
        List<BeVisitor> visitorList = new ArrayList<>();
        int num = 0;
        for (VisitorExcelDTO visitorExcelDTO : result) {
            num++;
            if (StringUtils.isBlank(visitorExcelDTO.getName())) {
                continue;
            }
            System.out.println(unit.getBeunitId());
            System.out.println(visitorExcelDTO.getDept());
            // 在查询部门是否存在
            BeDepartment department = beDepartmentService.query().eq("BEUNIT_ID", unit.getBeunitId()).eq("DEPARTMENT_NAME", visitorExcelDTO.getDept()).one();
            // 若存在就就保存人员
            if (Objects.nonNull(department)) {
                BeVisitor beVisitor = new BeVisitor();
                beVisitor.setBevisitorName(visitorExcelDTO.getName());
                beVisitor.setDeptId(department.getBedepartmentId());
                beVisitor.setPhoneNo(visitorExcelDTO.getPhone());
                visitorList.add(beVisitor);
            } else {
                // 若不存在就先保存部门再保存人员
                BeDepartment departmentNew = new BeDepartment();
                departmentNew.setDepartmentName(visitorExcelDTO.getDept());
                departmentNew.setBeunitId(unit.getBeunitId());
                beDepartmentService.save(departmentNew);
                BeVisitor beVisitor = new BeVisitor();
                beVisitor.setBevisitorName(visitorExcelDTO.getName());
                beVisitor.setDeptId(departmentNew.getBedepartmentId());
                beVisitor.setPhoneNo(visitorExcelDTO.getPhone());
                visitorList.add(beVisitor);
            }

        }
        beVisitorService.saveBatch(visitorList);
        System.out.println(num + ".........................");
        return Result.buildSuccess();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result applyFace(VisitorFaceDTO visitorFaceDTO) {
        // 获得陪同人员
        Visitor visitor = getById(visitorFaceDTO.getId());
        if (ObjectUtil.isNull(visitor)) {
            return Result.buildError("参数错误");
        }

        update().eq("ID", visitorFaceDTO.getId()).set("ID_CARD_IMG", visitorFaceDTO.getVisitorImg()).update();
        // 获得主访客的陪同人员
        Visitor mainVisitor = getById(visitor.getLeaderId());
        mainVisitor.setFollowFaceNum(mainVisitor.getFollowFaceNum() + 1);
        // 若随从人员人脸书别通过数量等于随从人员,并且预约开始时间大于今天
        if (mainVisitor.getFollowNum() == mainVisitor.getFollowFaceNum()
                && LocalDateTime.now().isAfter(mainVisitor.getAppointmentStartTime())) {
            //TODO 保存到短信数据库
            ShortMessage shortMessage = new ShortMessage();
            // 通过领导的ID查询手机号
            BeVisitor beVisitor = beVisitorService.getById(visitor.getBevisitorId());
            shortMessage.setPhoneNo(beVisitor.getPhoneNo());
            shortMessage.setName(beVisitor.getBevisitorName());
            shortMessage.setVisitorId(visitor.getId());
            shortMessage.setMessageType(0);
            shortMessage.setIsRead(0);
            shortMessage.setCreateTime(LocalDateTime.now());
        }
        updateById(mainVisitor);
        return Result.buildSuccess();
    }

    /**
     * 卫计委通用方法1
     *
     * @param apiKeyHealth
     * @param appIdHealth
     * @param appSecretHealth
     * @param urlHealth
     * @param id
     * @return
     */
    private cn.hutool.json.JSONObject Common(String apiKeyHealth, String appIdHealth, String appSecretHealth, String urlHealth, Long id) {
        //大数据局申请的apiKey，该部分需要替换
        String apiKey = apiKeyHealth;
        HttpHeaders headers = new HttpHeaders();
        headers.set("ApiKey", apiKey);
        //电子健康卡/码分配的授权，该部分需要替换
        String appId = appIdHealth;
        //电子健康卡/码分配的密钥，该部分需要替换
        String appSecret = appSecretHealth;

        RestTemplate restTemplate = new RestTemplate();
        //政务网地址
        String url = urlHealth;

        //组装参数
        cn.hutool.json.JSONObject paramJsonData = new cn.hutool.json.JSONObject();

        Visitor visitor = baseMapper.selectById(id);

        List<cn.hutool.json.JSONObject> jsonObjects = new ArrayList<>();

        paramJsonData.set("name", HealthCommissionUtils.encByAES(visitor.getVisitorName()));

        paramJsonData.set("cardNo", HealthCommissionUtils.encByAES(visitor.getIdCardNo()));
        //个人信息与二维码，二选一填写
        //paramJsonData.set("qrCode", "714C0A2AD6E603A755DBD0CA23FBBB63E6C8F7B999A99BF8E884B9B5D5930FCA:0:748FD3A74A91EC4CF95::");
        LinkedMultiValueMap<String, Object> linkedMap = new LinkedMultiValueMap<>();
        //生成时间戳
        String time = "" + System.currentTimeMillis();
        //生成随机字符串
        String nonceStr = RandomUtil.randomString(10);
        //获得签名值
        String str = appId + "&" + time + "&" + nonceStr;

        String sign = HealthCommissionUtils.genHMAC(str, appSecret);
        //将签名值添加到参数中
        linkedMap.add("sign", sign);

        linkedMap.add("appid", appId);

        linkedMap.add("nonce_str", nonceStr);

        linkedMap.add("time", time);

        linkedMap.add("paramJsonData", paramJsonData);

        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity(linkedMap, headers);
        //调用接口
        cn.hutool.json.JSONObject result = restTemplate.postForEntity(url, httpEntity, cn.hutool.json.JSONObject.class).getBody();

        return result;
    }

    /**
     * 卫健委通用方法2
     *
     * @param appIdHealth
     * @param appSecretHealth
     * @param urlHealth
     * @param id
     * @return
     */
    private cn.hutool.json.JSONObject Common1(String appIdHealth, String appSecretHealth, String urlHealth, Long id) {

        //电子健康卡/码分配的授权，该部分需要替换
        String appId = appIdHealth;
        //电子健康卡/码分配的密钥，该部分需要替换
        String appSecret = appSecretHealth;

        RestTemplate restTemplate = new RestTemplate();
        //政务网地址
        String url = urlHealth;

        //组装参数
        cn.hutool.json.JSONObject paramJsonData = new cn.hutool.json.JSONObject();

        Visitor visitor = baseMapper.selectById(id);

        List<cn.hutool.json.JSONObject> jsonObjects = new ArrayList<>();

        paramJsonData.set("outside", 0);

        paramJsonData.set("cardType", "01");

        paramJsonData.set("name", HealthCommissionUtils.encByAES(visitor.getVisitorName()));

        paramJsonData.set("cardNo", HealthCommissionUtils.encByAES(visitor.getIdCardNo()));
        //个人信息与二维码，二选一填写
        //paramJsonData.set("qrCode", "714C0A2AD6E603A755DBD0CA23FBBB63E6C8F7B999A99BF8E884B9B5D5930FCA:0:748FD3A74A91EC4CF95::");
        LinkedMultiValueMap<String, Object> linkedMap = new LinkedMultiValueMap<>();
        //生成时间戳
        String time = "" + System.currentTimeMillis();
        //生成随机字符串
        String nonceStr = RandomUtil.randomString(10);
        //获得签名值
        String str = appId + "&" + time + "&" + nonceStr;
        String sign = HealthCommissionUtils.genHMAC(str, appSecret);
        //将签名值添加到参数中
        linkedMap.add("sign", sign);
        linkedMap.add("appid", appId);
        linkedMap.add("nonce_str", nonceStr);
        linkedMap.add("time", time);
        linkedMap.add("paramJsonData", paramJsonData);
        //调用接口
        cn.hutool.json.JSONObject result = restTemplate.postForEntity(url, linkedMap, cn.hutool.json.JSONObject.class).getBody();

        return result;
    }


    /**
     * 通过leaderId查找随行访客信息
     *
     * @param id
     * @return
     */
    @Override
    public List<Visitor> getVisitorByLeaderId(Long id) {
        return baseMapper.getVisitorByLeaderId(id);
    }

    /**
     * 被访人确认
     * <p>
     * 发短信给访客
     *
     * @param id 主访客id
     * @return
     */
    @Override
    public Result confirm(Long id) {

        Visitor mainVisitor = baseMapper.selectById(id);

        if (Objects.nonNull(mainVisitor)) {

            //1是成功
            baseMapper.updateById(mainVisitor.setState("1"));

        } else {

            return Result.buildError("用户不存在！");
        }

        List<Visitor> visitorByLeader = baseMapper.getVisitorByLeaderId(id);

        if (!CollectionUtils.isEmpty(visitorByLeader)) {

            //1是成功
            visitorByLeader.forEach(visitor -> baseMapper.updateById(visitor.setState("1")));

        }

        //更改完数据库状态之后挨个给方可发短信通知预约成功
        List<Visitor> visitor = getVisitor(id);

        for (Visitor v : visitor) {

            // todo 短信模板需要更改
            Map<String, String> map = new LinkedHashMap<>(2);

            map.put("name", v.getVisitorName());

            map.put("code", v.getId().toString());

            try {

                AliSmsUtils.sendSms(v.getPhoneNo(), Constant.SMS_VISITOR_SUCCESSCODE, map);

            } catch (ClientException e) {

                e.printStackTrace();

                String error = "短信发送失败，请稍后重试";

                throw new BaseException(-2, error);

            }

        }

        return Result.buildSuccess();
    }

    /**
     * 被访人拒绝访客申请
     * <p>
     * 发短信给访客
     *
     * @param id 主访客id
     * @return
     */
    @Override
    public Result refuse(Long id) {

        Visitor mainVisitor = baseMapper.selectById(id);

        if (Objects.nonNull(mainVisitor)) {

            //2是失败
            baseMapper.updateById(mainVisitor.setState("2"));

        } else {

            return Result.buildError("用户不存在！");
        }

        List<Visitor> visitorByLeader = baseMapper.getVisitorByLeaderId(id);

        if (!CollectionUtils.isEmpty(visitorByLeader)) {

            //2是失败
            visitorByLeader.forEach(visitor -> baseMapper.updateById(visitor.setState("2")));

        }

        //更改完数据库状态之后挨个给方可发短信通知预约成功
        List<Visitor> visitor = getVisitor(id);

        for (Visitor v : visitor) {

            // todo 短信模板需要更改
            Map<String, String> map = new LinkedHashMap<>(2);

            map.put("name", v.getVisitorName());

            map.put("code", v.getId().toString());

            try {

                AliSmsUtils.sendSms(v.getPhoneNo(), Constant.SMS_VISITOR_FAILCODE, map);

            } catch (ClientException e) {

                e.printStackTrace();

                String error = "短信发送失败，请稍后重试";

                throw new BaseException(-2, error);

            }

        }

        return Result.buildSuccess();
    }

    /**
     * 通过被访人姓名调取海康接口(查询人员列表v2)
     * <p>
     * 被访人id 通过数据库的id找到被访人的名字  在通过被访人的名字找到海康平台上被访人的id(被访人的名字只找到一个)   已过
     *
     * @param id
     * @return
     */
    @Override
    public String personId(Long id) {

        GetCameraPreviewURL cameraPreviewURL = new GetCameraPreviewURL(Configure.host, Configure.appKey, Configure.appSecret);

        Person person = new Person();

        //从我们的数据库里通过访客id关联查到被访人姓名
        String beVisitorName = getBevisitorName(id);

        person.setPersonName(beVisitorName);

        person.setPageNo(1);

        person.setPageSize(999);

        //海康查询人员列表v2(在海康平台里通过被访人行名查到被访人id)
        String s = cameraPreviewURL.doPost(GetCameraPreviewURL.ARTEMIS_PATH + VisitorAppointmentURL.QUERY_PERSON_LIST, JSON.toJSONString(person));

        net.sf.json.JSONObject jsonObjectP = net.sf.json.JSONObject.fromObject(s);

        Map<String, Class> classMap = new HashMap<>();

        //组装海康门禁返回数据
        classMap.put("data", PersonData.class);

        classMap.put("list", PersonList.class);

        classMap.put("personPhoto", PersonPhotoRes.class);

        Result personResult = (Result) net.sf.json.JSONObject.toBean(jsonObjectP, Result.class, classMap);

        PersonData data = (PersonData) personResult.getData();

        List<PersonList> list = data.getList();

        String personId = "";

        for (PersonList p : list) {
            personId = p.getPersonId();
        }
        return personId;
    }

    /**
     * 获取访客二维码信息
     * <p>
     * 海康预约免登记接口
     *
     * @param receptionistId
     * @return
     */
    @Override
    public List<String> QRCode(Long receptionistId) {

        GetCameraPreviewURL cameraPreviewURL = new GetCameraPreviewURL(Configure.host, Configure.appKey, Configure.appSecret);

        List<Visitor> visitorList = getVisitor(receptionistId);

        List<com.ydzh.kfqgwvisitor.hikdata.hikreq.visitor.Visitor> visitors = new ArrayList<>();

        //通过海康平台查到被访人id
        String rd = personId(receptionistId);

        for (Visitor vv : visitorList) {

            com.ydzh.kfqgwvisitor.hikdata.hikreq.visitor.Visitor visitor = new com.ydzh.kfqgwvisitor.hikdata.hikreq.visitor.Visitor();

            visitor.setReceptionistId(rd);

            visitor.setVisitStartTime(TimeUtils.getISO8601ToStr(vv.getAppointmentStartTime()));

            visitor.setVisitEndTime(TimeUtils.getISO8601ToStr(vv.getAppointmentEndTime()));

            VisitorInfo visitorInfo = new VisitorInfo();

            visitorInfo.setVisitorName(vv.getVisitorName());

            visitorInfo.setGender(Integer.valueOf(vv.getSex()));

            visitorInfo.setPhoneNo(vv.getPhoneNo());

            visitorInfo.setCertificateNo(vv.getIdCardNo());

            //来访车牌号
            visitorInfo.setPlateNo(vv.getVehicleNo());

            //证件类型为身份证
            visitorInfo.setCertificateType(111);

            //加入卡号，配合海康测试！！！！！
            visitorInfo.setCardNo(vv.getIdCardNo());

            String base64 = baseMapper.getBase64(receptionistId);

            visitorInfo.setVisitorPhoto(base64);

            visitor.setVisitorInfo(visitorInfo);

            visitors.add(visitor);

        }

        List<String> qrCodeList = new ArrayList<>();

        for (com.ydzh.kfqgwvisitor.hikdata.hikreq.visitor.Visitor v : visitors) {

            //海康预约免登记
            String s = cameraPreviewURL.doPost(GetCameraPreviewURL.ARTEMIS_PATH + VisitorAppointmentURL.RESERVATION_FREE_REGISTRATION, JSON.toJSONString(v));

            net.sf.json.JSONObject jsonObjectP = net.sf.json.JSONObject.fromObject(s);

            if ("0x0531401d".equals(jsonObjectP.get("code"))) {

                throw new BaseException(-2, "预约时间冲突！请重新选择预约时间！");
            }

            Map<String, Class> classMap = new HashMap<>();

            //组装海康返回数据
            classMap.put("data", VisitorData.class);

            Result personResult = (Result) net.sf.json.JSONObject.toBean(jsonObjectP, Result.class, classMap);

            VisitorData data = (VisitorData) personResult.getData();

            String qrCode = data.getQRCode();

            //通过证件号码找到访客并与之qrCode进行绑定
            Visitor byIdCardNo = baseMapper.getByIdCardNo(v.getVisitorInfo().getCertificateNo());

            byIdCardNo.setQRCode(qrCode);

            //把带有qrCode的访客插入数据库
            baseMapper.updateById(byIdCardNo);

            qrCodeList.add(qrCode);
        }

        //返回qrCode集合
        return qrCodeList;
    }

    /**
     * 根据id查找被访人姓名
     *
     * @param id
     * @return
     */
    @Override
    public String getBevisitorName(Long id) {

        return baseMapper.getBevisitorName(id);
    }

    /**
     * 通过访客id获取Visitor集合(包括主访客和随行访客)
     *
     * @param id
     * @return
     */
    private List<Visitor> getVisitor(Long id) {

        List<Visitor> visitorList = new ArrayList<>();

        //查找主访客
        visitorList.add(baseMapper.selectById(id));

        //随行访客list
        for (Visitor visitor : getVisitorByLeaderId(id)) {

            visitorList.add(visitor);

        }
        return visitorList;
    }

    /**
     * 测试卫健委接口
     *
     * @param args
     */
    public static void main(String[] args) {

        //大数据局申请的apiKey，该部分需要替换
//        String apiKey = "879756809923985408";
//        HttpHeaders headers = new HttpHeaders();
//        headers.set("ApiKey", apiKey);
//        //电子健康卡/码分配的授权，该部分需要替换 e4e5de481a1245d1b04e6b96ceb0f4e1
//        //zogwkbf3u71o7feumb3m  iao4p1fjbq37misom68w
//        String appId = "iao4p1fjbq37misom68w";
//        //电子健康卡/码分配的密钥，该部分需要替换 e4e5de481a1245d1b04e6b96ceb0f4e1
//        String appSecret = "24f8875c9c7d45419acde17d88bb8b62";
//
//        RestTemplate restTemplate = new RestTemplate();
//        //政务网地址
//        String url = "http://59.224.6.2/gateway/api/11/getVaccineRecordExt";
//
//        //组装参数
//        cn.hutool.json.JSONObject paramJsonData = new cn.hutool.json.JSONObject();
//
//        paramJsonData.set("name", HealthCommissionUtils.encByAES("王世玺"));
//        paramJsonData.set("cardNo", HealthCommissionUtils.encByAES("23070319870301051X"));
//        //个人信息与二维码，二选一填写
//        //paramJsonData.set("qrCode", "714C0A2AD6E603A755DBD0CA23FBBB63E6C8F7B999A99BF8E884B9B5D5930FCA:0:748FD3A74A91EC4CF95::");
//        LinkedMultiValueMap<String, Object> linkedMap = new LinkedMultiValueMap<>();
//        //生成时间戳
//        String time = "" + System.currentTimeMillis();
//        //生成随机字符串
//        String nonceStr = RandomUtil.randomString(10);
//        //获得签名值
//        String str = appId + "&" + time + "&" + nonceStr;
//        String sign = HealthCommissionUtils.genHMAC(str, appSecret);
//        //将签名值添加到参数中
//        linkedMap.add("sign", sign);
//        linkedMap.add("appid", appId);
//        linkedMap.add("nonce_str", nonceStr);
//        linkedMap.add("time", time);
//        linkedMap.add("paramJsonData", paramJsonData);
//        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity(linkedMap, headers);
//        //调用接口
//        cn.hutool.json.JSONObject result = restTemplate.postForEntity(url, httpEntity, cn.hutool.json.JSONObject.class).getBody();
//        cn.hutool.json.JSONObject jsonObject = result.getJSONObject("data").getJSONObject("data").getJSONObject("data");
//        System.out.println(jsonObject);
//        System.out.println(jsonObject.get("flag"));

        String appId = "iix0iqj8f8e5uz3qpxr1";
        //电子健康卡/码分配的密钥，该部分需要替换 e4e5de481a1245d1b04e6b96ceb0f4e1
        String appSecret = "5dbe209632824914836bfb9c0bf8b6f3";

        RestTemplate restTemplate = new RestTemplate();

        String url = "http://172.20.238.8:4431/passDataExchangeService/dataExchange/getHealthPassByUserInfo";

        //组装参数
        cn.hutool.json.JSONObject paramJsonData = new cn.hutool.json.JSONObject();

        paramJsonData.set("outside", 0);
        paramJsonData.set("cardType", "01");
        paramJsonData.set("name", HealthCommissionUtils.encByAES("许晖"));
        paramJsonData.set("cardNo", HealthCommissionUtils.encByAES("62040219900725091X"));
        //个人信息与二维码，二选一填写
        //paramJsonData.set("qrCode", "714C0A2AD6E603A755DBD0CA23FBBB63E6C8F7B999A99BF8E884B9B5D5930FCA:0:748FD3A74A91EC4CF95::");
        LinkedMultiValueMap<String, Object> linkedMap = new LinkedMultiValueMap<>();
        //生成时间戳
        String time = "" + System.currentTimeMillis();
        //生成随机字符串
        String nonceStr = RandomUtil.randomString(15);
        //获得签名值
        String str = appId + "&" + time + "&" + nonceStr;
        String sign = HealthCommissionUtils.genHMAC(str, appSecret);
        //将签名值添加到参数中
        linkedMap.add("sign", sign);
        linkedMap.add("appid", appId);
        linkedMap.add("nonce_str", nonceStr);
        linkedMap.add("time", time);
        linkedMap.add("paramJsonData", paramJsonData);
        //HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity(linkedMap, headers);
        //调用接口
        cn.hutool.json.JSONObject result = restTemplate.postForEntity(url, linkedMap, cn.hutool.json.JSONObject.class).getBody();

        System.out.println(result);

        System.out.println(result.getJSONObject("data"));

        System.out.println(result.getJSONObject("data").get("state"));

    }
}
